import axios from 'axios';
import Interceptors from './Interceptors';
import { DOMAIN_SYSTEM_ENUM, type IUserRequestConfig, type IPromise, type IResponse } from './types';
import qs from 'qs';

export default class Http {
  private instance = axios.create({
    baseURL: import.meta.env.VITE_APP_BASE_API,
    timeout: 1000 * 50,
    headers: { 'Content-Type': 'application/json;charset=utf-8' },
    paramsSerializer: (params) => qs.stringify(params),
  });

  private interceptors = new Interceptors();

  constructor() {
    const { request, response } = this.instance.interceptors;
    request.use(
      (config) => this.interceptors.requestDefaultLoading(config),
      (error) => Promise.reject(error)
    );
    request.use((config) => this.interceptors.requestDuplicateCancel(config));
    request.use((config) => this.interceptors.requestConfigUrl(config));
    request.use((config) => this.interceptors.requestParams(config));
    request.use((config) => this.interceptors.requestHeader(config));

    response.use((response) => this.interceptors.responseDuplicateCancel(response));
    response.use((response) => this.interceptors.responseDefaultLoading(response));
    response.use((response) => this.interceptors.responseSuccess(response));
    response.use(
      (response) => this.interceptors.responseError(response),
      (err) => this.interceptors.handleError(err)
    );
  }

  get<T = any>({ ...requestConfig }: IUserRequestConfig): IPromise<T> {
    return this.request<IResponse<T>>({ method: 'GET', ...requestConfig }).then((res) => res.data);
  }

  post<T = any>({ ...requestConfig }: IUserRequestConfig): IPromise<T> {
    return this.request<IResponse<T>>({ method: 'POST', ...requestConfig }).then((res) => res.data);
  }

  put<T = any>({ ...requestConfig }: IUserRequestConfig): IPromise<T> {
    return this.request<IResponse<T>>({ method: 'PUT', ...requestConfig }).then((res) => res.data);
  }

  delete<T = any>({ ...requestConfig }: IUserRequestConfig): IPromise<T> {
    return this.request<IResponse<T>>({ method: 'DELETE', ...requestConfig }).then((res) => res.data);
  }

  patch<T = any>({ ...requestConfig }: IUserRequestConfig): IPromise<T> {
    return this.request<IResponse<T>>({ method: 'PATCH', ...requestConfig }).then((res) => res.data);
  }

  async request<T = any>({
    method = 'GET',
    params = {},
    data = {},
    config = {},
    ...requestConfig
  }: IUserRequestConfig) {
    const defaultConfig: IUserRequestConfig = {
      // TODO: 根据不同的系统，配置不同的 server
      server: DOMAIN_SYSTEM_ENUM.BAIDU,
      // 请求 url
      url: '',
      method,
      params,
      data,
      config,
      loading: false,
      loadingMessage: '加载中...',
      responseType: 'json',
      isCancelDuplicateUrlRequests: false,
      isNotCancel: false,
      ...config,
    };

    const mergeConfig = Object.assign(
      {},
      {
        ...defaultConfig,
        ...requestConfig,
      }
    );

    // if (method === 'GET' || method === 'DELETE') {
    //   mergeConfig.paramsSerializer = (requestParams: any) => {
    //     return qs.stringify(requestParams);
    //   };
    // }

    return this.instance.request<T>(mergeConfig);
  }
}
